//
//  NSString+path.m
//  helper
//
//  Created by huangyi on 12-10-29.
//  Copyright (c) 2012年 huangyi. All rights reserved.
//

#import "NSString+path.h"
#import "NSData+utils.h"

extern NSString* uniqueID();

static void emptyTrash(){
    static dispatch_queue_t queue=NULL;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue=dispatch_queue_create("empty-trash-queue", 0);
    });
    dispatch_async(queue, ^{
        NSString *directory=@"".trashPath;
        NSArray *list=[directory listDir];
        for (NSString *file in list) {
            NSString *path=[directory stringByAppendingPathComponent:file];
            NSError *error=nil;
            [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
            if (error) {
                NSLog(@"%@",error.description);
            }
        }
        NSLog(@"Empty Trash");
    });
}
static BOOL moveToTrash(NSString *path){
    static dispatch_queue_t queue=NULL;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue=dispatch_queue_create("move-to-trash-queue", 0);
    });
    NSString *dirToDelete=nil;
    do {
        dirToDelete=[path.lastPathComponent stringByAppendingString:@"-"];
        dirToDelete=[dirToDelete stringByAppendingString:uniqueID()];
        dirToDelete=dirToDelete.trashPath;
    } while (dirToDelete.isFileOrDir);
    if ([path moveTo:dirToDelete]) {
        dispatch_async(queue, ^{
            NSError *error=nil;
            [[NSFileManager defaultManager] removeItemAtPath:dirToDelete error:&error];
            if (error) {
                NSLog(@"%@",error.description);
            }else{
                NSLog(@"Deleted (%@)",path);
            }
        });
        return YES;
    }else{
        return NO;
    }
}


@implementation NSString (path)

-(BOOL)isDir{
    BOOL isDir;
    if ([[NSFileManager defaultManager] fileExistsAtPath:self isDirectory:&isDir]) {
        if (isDir) {
            return YES;
        }else{
            return NO;
        }
    }else{
        return NO;
    }
}
-(BOOL)isFile{
    BOOL isDir;
    if ([[NSFileManager defaultManager] fileExistsAtPath:self isDirectory:&isDir]) {
        if (isDir) {
            return NO;
        }else{
            return YES;
        }
    }else{
        return NO;
    }
}
-(BOOL)isFileOrDir{
    BOOL isDir;
    if ([[NSFileManager defaultManager] fileExistsAtPath:self isDirectory:&isDir]) {
        return YES;
    }else{
        return NO;
    }
}
-(BOOL)isWriteable{
    NSString *path=[NSString stringWithString:self];
    int loop=64;//max folder depth
    while (loop) {
        if (!path.isFileOrDir) {
            path=path.stringByDeletingLastPathComponent;
        }
        loop--;
    }
    return [[NSFileManager defaultManager] isWritableFileAtPath:path];
}

-(NSArray*)listDir{
    NSError *error=nil;
    NSArray *items=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:self error:&error];
    if (error) {
        NSLog(@"%@",error.description);
    }
    return items;
}

-(BOOL)createDir{
    if (!self.isDir) {
        NSMutableArray *parent=[NSMutableArray arrayWithArray:self.pathComponents];
        NSString *fp=@"";
        while (parent.count) {
            fp=[fp stringByAppendingPathComponent:[parent objectAtIndex:0]];
            [parent removeObjectAtIndex:0];
            if (!fp.isDir) {
                NSError *error=nil;
                [[NSFileManager defaultManager] createDirectoryAtPath:self withIntermediateDirectories:YES attributes:nil error:&error];
                if (error) {
                    NSLog(@"%@",error.description);
                    return NO;
                }
            }
        }
    }
    return self.isDir;
}
-(BOOL)removeDir{
    if (self.isDir) {
        moveToTrash(self);
    }
    return !self.isFileOrDir;
}
-(BOOL)removeDirContents{
    [self removeDir];
    [self createDir];
    return self.isDir;
}
-(BOOL)createFile{
    NSString *fp=self.stringByDeletingLastPathComponent;
    if (fp.createDir) {
        [[NSFileManager defaultManager] createFileAtPath:self contents:nil attributes:nil];
        return self.isFile;
    }else{
        return NO;
    }
}
-(BOOL)removeFile{
    if (self.isFile) {
        moveToTrash(self);
    }
    return !self.isFileOrDir;
}
-(BOOL)removeFileOrDir{
    if (self.isFile) {
        [self removeFile];
    }
    if (self.isDir){
        [self removeDir];
    }
    return self.isFileOrDir;
}

-(NSString*)rootPath{
    NSString *dir=NSHomeDirectory();
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}
-(NSString*)docPath{
    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    if (!paths.count) {
        return nil;
    }
    NSString *dir=[paths objectAtIndex:0];
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}
-(NSString*)cachePath{
    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    if (!paths.count) {
        return nil;
    }
    NSString *dir=[paths objectAtIndex:0];
    if (!dir.isDir) {
        [dir createDir];
    }
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}
-(NSString*)tempPath{
    NSString *dir=NSTemporaryDirectory();
    if (!dir.isDir) {
        [dir createDir];
    }
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}
-(NSString*)trashPath{
    NSString *dir=@"trashbin".tempPath;
    if (!dir.isDir) {
        [dir createDir];
    }
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}
-(NSString*)appPath{
    NSString *dir=[[NSBundle mainBundle] bundlePath];
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}
-(NSString*)mediaPath{
    NSString *dir=[[NSBundle mainBundle] bundlePath];
    dir=[dir stringByAppendingPathComponent:@"media"];
    if (!dir.isDir) {
        NSCAssert(0, @"media directory (%@) not exist",dir);
    }
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}

-(NSDate*)fileCreationDate{
    if (self.isFileOrDir) {
        NSError *error=nil;
        NSDictionary *attr=[[NSFileManager defaultManager] attributesOfItemAtPath:self error:&error];
        if (error) {
            NSLog(@"%@",error.description);
        }
        NSDate *modified=[attr valueForKey:NSFileCreationDate];
        return modified;
    }else{
        return nil;
    }
}
-(NSDate*)fileModificationDate{
    if (self.isFileOrDir) {
        NSError *error=nil;
        NSDictionary *attr=[[NSFileManager defaultManager] attributesOfItemAtPath:self error:&error];
        if (error) {
            NSLog(@"%@",error.description);
        }
        NSDate *modified=[attr valueForKey:NSFileModificationDate];
        return modified;
    }else{
        return nil;
    }
}
-(NSUInteger)fileSize{
    if (self.isFileOrDir) {
        NSError *error=nil;
        NSDictionary *attr=[[NSFileManager defaultManager] attributesOfItemAtPath:self error:&error];
        if (error) {
            NSLog(@"%@",error.description);
        }
        NSNumber *bytes=[attr valueForKey:NSFileSize];
        return bytes.unsignedIntegerValue;
    }else{
        return 0;
    }
}

-(NSData*)read{
    NSData *data=nil;
    NSFileHandle *fp=[NSFileHandle fileHandleForReadingAtPath:self];
    [fp seekToFileOffset:0];
    data=[fp readDataToEndOfFile];
    [fp closeFile];
    return data;
}
-(BOOL)write:(NSData*)data{
    if (!self.isFile) {
        [self createFile];
    }
    NSFileHandle *fp=[NSFileHandle fileHandleForWritingAtPath:self];
    [fp truncateFileAtOffset:0];
    [fp writeData:data];
    [fp closeFile];
    return YES;
}
-(BOOL)append:(NSData *)data{
    if (!self.isFile) {
        [self createFile];
    }
    NSFileHandle *fp=[NSFileHandle fileHandleForWritingAtPath:self];
    [fp seekToEndOfFile];
    [fp writeData:data];
    [fp closeFile];
    return YES;
}
-(BOOL)moveTo:(NSString*)path{
    if (self.isFileOrDir) {
        NSString *dir=self.stringByDeletingLastPathComponent;
        if (!dir.isDir) {
            [dir createDir];
        }
        NSError *error=nil;
        [[NSFileManager defaultManager] moveItemAtPath:self toPath:path error:&error];
        if (error) {
            NSLog(@"%@",error.description);
            return NO;
        }
    }else{
        return NO;
    }
    return path.isFileOrDir;
}
-(BOOL)copyTo:(NSString*)path{
    if (self.isFileOrDir) {
        NSString *dir=self.stringByDeletingLastPathComponent;
        if (!dir.isDir) {
            [dir createDir];
        }
        NSError *error=nil;
        [[NSFileManager defaultManager] copyItemAtPath:self toPath:path error:&error];
        if (error) {
            NSLog(@"%@",error.description);
            return NO;
        }
    }else{
        return NO;
    }
    return path.isFileOrDir;
}
-(BOOL)moveToDir:(NSString*)path{
    NSString *filename=self.lastPathComponent;
    path=[path stringByAppendingPathComponent:filename];
    return [self moveTo:path];
}
-(BOOL)copyToDir:(NSString*)path{
    NSString *filename=self.lastPathComponent;
    path=[path stringByAppendingPathComponent:filename];
    return [self copyTo:path];
}

-(NSData*)fileData{
    NSData *data=nil;
    NSError *error=nil;
    data=[NSData dataWithContentsOfFile:self options:NSDataReadingUncached error:&error];
    if (error) {
        NSLog(@"%@",error.description);
    }
    return data;
}

-(NSString*)userPath{
    NSData *fp=[@"user".docPath read];
    NSString *user=fp.stringValue;
    if (user==nil) {
        user=@"public";
    }
    user=[NSString stringWithFormat:@"users/%@",user];
    NSString *dir=user.cachePath;
    if (!dir.isDir) {
        [dir createDir];
    }
    if (self.length) {
        return [dir stringByAppendingPathComponent:self];
    }else{
        return dir;
    }
}

@end
